Temgen mo¿e s³u¿yæ do generowania dowolnych tekstów, w których wystêpuj± powtarzalne wzorce. Poniewa¿ ca³a logika generacji zawarta jest w szablonach, temgen mo¿e byæ u¿ywany do generowania kodu w dowolnym jêzyku, np. w C, Perlu, HTML, czy angielskim.
Mechanizm @embed i @emit pozwala na elastyczne tworzenie szablonów generuj±cych synchronicznie fragmenty kodu w wielu plikach i w ró¿nych punktach.
Temgen wywo³uje siê w nastêpuj±cy sposób: | |
---|---|
temgen [opcje] file ... |
Obs³ugiwane s± nastêpuj±ce opcje:
Podstawy | S³owa kluczowe | Funkcje wbudowane |
---|---|---|
Przebieg wykonania generacji jest nastêpuj±cy: pliki ¼ród³owe wyszczególnione w linii komend s± parsowane w ca³o¶ci, a nastêpnie s± po kolei interpretowane. Interpretacja odbywa siê linia po linii, przy czym kolejno¶æ ta mo¿e zostaæ zmieniona w wyniku interpretacji linii steruj±cych. Plik ¼ród³owy (szablon) sk³ada siê z dwóch rodzajów linii: linii steruj±cych i linii danych.
Linie steruj±ce rozpoczynaj± siê od znaku @ i identyfikatora komendy. Komendy wyszczególnione s± w tabelce powy¿ej i omówione ni¿ej. S³u¿± do zmiany przebiegu interpretacji (np. @if, @switch), do deklarowania funkcji ( @function ), wykonywania fragmentów kodu, np. w celu nadania pewnych warto¶ci zmiennym ( @ ), a tak¿e okre¶lenia pliku wyj¶ciowego i punktu, w którym ma byæ umieszczony generowany kod ( @output, @embed, @emit ). Linie steruj±ce mog± byæ kontynuowane w kolejnym wierszu. Linia kontynuowana musi koñczyæ siê znakiem backslashem, a w kolejnym wierszu rozpoczynaæ siê znakiem @.
Kontynuacja linii steruj±cej: | |
---|---|
@if ( $bardzo_dlugie_wyrazenie == \ @ $dalszy_ciag_dlugiego_wyrazenia ) |
Linie danych zawieraj± tekst generowanego kodu. Tekst ten ulega rozwiniêciu polegaj±cemu na zast±pieniu wystêpuj±cych w nim wyra¿eñ odpowiednimi warto¶ciami. Po rozwiniêciu tekst wstawiany jest w punkcie emisji. Punkt ten standardowo znajduje siê na koñcu aktualnego pliku wyj¶ciowego, mo¿e byæ jednak zmieniony przy u¿yciu komend @emit i @embed. Plik wyj¶ciowy mo¿e zostaæ ustalony za pomoc± komendy @output.
Linie danych (szablon i wynik) | |
---|---|
@ $name = "Alaska" $name is the best ! | Alaska is the best ! |
W celu ochrony napisów przed ich interpretacj± jako wyra¿eñ nale¿y u¿ywaæ backslasha, który wymusza dos³owne traktowanie tekstu.
Escaping (szablon i wynik) | |
---|---|
@ $name = "Alaska" (zmienna \$name) | (zmienna $name) |
Skalary, tablice i struktury | |
---|---|
@ $s = "BAR" @ $n = 2 @ $tab[1] = "foo" @ $tab[2] = "bar" @ $str = [ name: "FOO", count: 4 ] $s $tab[ 1 ] $tab[ $n ] $str.name, $str.count | BAR foo bar FOO, 4 |
Tablice i struktury - iterowanie | |
---|---|
@ $tab = ["a","b","c",1000] @ $str = [ name: "FOO", count: 4, val: 1.20 ] @for ($i=0; $i<$size($tab); $i++) item $i: $tab[ $i ] @endfor STRUCTURE: @for ($i in $str) $i: $str.$i @endfor | item 0: a item 1: b item 2: c item 3: 1000 STRUCTURE: name: FOO count: 4 val: 1.200000 |
Tablice i struktury mog± byæ dowolnie zagnie¿d¿ane:
Zagnie¿d¿one struktury danych: | |
---|---|
@ $data = [ "scalar", [a:"Alaska", b:"Bar"], \ @ [1,2,3,4], \ @ 10 ] |
Dostêpne operatory (semantyka jak w jêzyku C): | |
---|---|
- == ++ (postfiksowy i prefiksowy) + != -- (postfiksowy i prefiksowy) * = && / < || -= > += <= *= >= /= ! |
Przyk³ady wyra¿eñ: | |
---|---|
1 1.01 "foo" 'bar' $x -= 10 [ 1, 2, "FOO" ] [ name: "foo", val: 0 ] $fun( 10, $x ) $var.x $var.$field $tab[ 10 ] $( 'Foo bar bazoola' ) | liczby i napisy wyra¿enie arytmetyczne konstruktor tablicy konstruktor struktury wywo³anie funkcji selektor (dostêp do pola) selektor (dostêp do pola przez nazwê) selektor (dostêp do elementu) wyra¿enie w nawiasach |
Interpretacja linii danych polega na zast±pieniu wystêpuj±cych w niej wyra¿eñ przez ich obliczone warto¶ci. Je¿eli wyra¿enie jest wywo³aniem funkcji, warto¶ci± jest dana zwrócona z wewn±trz funkcji za pomoc± instrukcji @return. Interpretacja linii danych zawartych wewn±trz takiej funkcji nie powoduje emitowania tekstu. Odwrotnie jest w przypadku wywo³ania funkcji z linii kontrolnej. Warto¶æ zwracana za pomoc± instrukcji @return jest wtedy ignorowana, a linie danych z wnêtrza funkcji emitowane s± na wyj¶ciu. Brzmi to zawile, ale staje siê jasne po zapoznaniu siê z przyk³adem:
Wywo³anie funkcji: | |
---|---|
@function fun() inline text @ return "RESULT TEXT" @endfunction called from data line: $fun() @ $fun() | called from data line: RESULT TEXT inline text |
Komendy steruj±ce
Komendy - wyra¿enia | |
---|---|
@ $fun() @ $x = 1 |
Komenda @break dzia³a podobnie jak instrukcja break w jêzyku C. Przerywa pêtle @for i instrukcjê @switch.
Komenda @break: | |
---|---|
@for ( $i=0; $i<10; $i++ ) iteration $i @ break @endfor @switch ( 1 ) @ case 1: branch 1 @ break @ case 2: branch 2 @endswitch | iteration 0 branch 1 |
Para komend @embed i @emit umo¿liwia zmianê kolejno¶ci generowanych linii. @embed pozwala zdefiniowaæ punkt, w którym emitowany bêdzie tekst, @emit skierowuje strumieñ wyj¶cia do zdefiniowanego gdziekolwiek punktu. Wa¿ne jest to, ¿e punkt ten (definiowany przez @embed) mo¿e byæ zadeklarowany w innym pliku ¼ród³owym, po - lub przed u¿yciem @emit i mo¿e le¿eæ w innym pliku wyj¶ciowym. Komendy te wraz z @pop, @push i @output stanowi± jeden z najsilniejszych mechanizmów temgena.
Argumentem komend @embed i @emit mo¿e byæ dowolne wyra¿enie, nie koniecznie sta³y napis.
@embed 'Nazwa' oznacza: tu emituj tekst po napotkaniu @emit 'Nazwa'.
@emit 'Nazwa' oznacza: emituj tekst w punkcie oznaczonym @embed 'Nazwa'.
Punkty emisji: | |
---|---|
@embed "header" @embed "body" @embed "footer" @emit "body" BODY TEXT @emit "footer" FOOTER TEXT @emit "header" HEADER TEXT | HEADER TEXT BODY TEXT FOOTER TEXT |
Podstawowa forma pêtli @for dzia³a podobnie jak w jêzyku C . Pêtla mo¿e zostaæ przerwana komend± @break. Druga forma umo¿liwia iteracjê pól struktury o nieznanych apriori nazwach.
Pêtle: | |
---|---|
@for ( $i=0; $i<3; $i++ ) item $i @endfor @ $str = [ a: "FOO", b: "BAR" ] @for ( $fld in $str ) $fld: $str.$fld @endfor | item 0 item 1 item 2 a: FOO b: BAR |
Komenda @function s³u¿y do definiowania funkcji. W nag³ówku funkcji podaje siê nazwy parametrów. Komenda @return s³u¿y do zwracania rezultatu funkcji. Efekt wywo³ania funkcji zale¿y od tego, czy wywo³ano j± z linii danych, czy z linii kontrolnej. Zosta³o to omówione powy¿ej. Funkcje mog± byæ wywo³ywane w dowolnym pliku ¼ród³owym, przed, lub po deklaracji. Do deklarowania zmiennych lokalnych s³u¿y komenda @local.
Funkcja: | |
---|---|
@function factor( n ) @ if ( $n == 1 ) @ return 1 @ else @ return $n * $factor( $n - 1 ) @ endif @endfunction @for ( $i=1; $i<8; $i++ ) $i ! = $factor($i) @endfor | 1 ! = 1 2 ! = 2 3 ! = 6 4 ! = 24 5 ! = 120 6 ! = 720 7 ! = 5040 |
Konstrukcja @if jest klasyczna. Nie wymaga komentarza. Jest zaprezentowana w wielu przyk³adach.
Instrukcja @local s³u¿y do deklarowania lokalnych zmiennych wewn±trz funkcji.
Zmienna lokalna: | |
---|---|
@function abc(a,b) @local c $a $b $c @ $a='anew' @ $b='bnew' @ $c='cnew' $a $b $c @endfunction @ $a='a' @ $b='b' @ $c='c' $a $b $c @ $abc( $a, $b ) $a $b $c | a b c a b anew bnew cnew a b c |
Interpretacja komendy @output powoduje prze³±czenie wyj¶cia do pliku o nazwie podanej jako argument. Razem z komendami @embed, @emit, @pop i @push tworzy zestaw umo¿liwiaj±cy sterowanie wyj¶ciem. Specjalna nazwa pliku "stdout" s³u¿y do przekierowania wyniku na standardowe wyj¶cie programu.
Sterowanie wyj¶ciem: | |
---|---|
@output "foo" FOO @output "stdout" STDOUT |
Komendy @pop i push s³u¿± do zachowania i odtworzenia punktu emisji. Punkt emisji ustalany jest przez wykonanie komend @output (plik) i @emit (linia). @pop i @push przydatne s± wewn±trz funkcji, pozwalaj±c odtworzyæ stan punktu emisji sprzed jej wywo³ania.
@Push i @pop: | |
---|---|
@function decl( d ) @ push @ output "example.h" $d @ pop @endfunction @output "example.c" #include "example.h" @ $decl( "int i;" ) int main() { @ $decl( "int result;" ) return result; } | example.h: int i; int result; example.c: #include "example.h" int main() { return result; } |
Instrukcja @return umo¿liwia zakoñczenie wykonania funkcji i zwrócenie rezultatu.
Komenda @switch ma sk³adniê podobn± do analogicznej instrukcji jêzyka C. Ró¿nica polega na tym, ¿e etykietami mog± byæ dowolne wyra¿enia, co ilustruje poni¿szy przyk³ad. Instrukcja @break ma tu zastosowanie analogiczne jak w jêzyku C.
Komenda @switch: | |
---|---|
@function string( len ) @ if ( $len == 1 ) @ return "z" @ else @ return "z" + $string( $len-1 ) @ endif @endfunction @switch "zz" @ case $string(1) : 1 @ break @ case $string(2) : 2 @ break @ case $string(3) : 3 @ break @endswitch | 2 |
Komenda @use: | |
---|---|
@use "foo.tg" @ $foo() | FOO |
Funkcja $printf s³u¿y do formatowania wyra¿eñ i dzia³a podobnie do funkcji z rodziny printf (3).
$printf() | |
---|---|
$printf( "%-10s %d 0x%02X", "foo", 10, 10 ) | foo 10 0x0A |
Funkcja $size zwraca rozmiar (liczbê pól) obiektu z³o¿onego.
$size() | |
---|---|
@ $x = 1 @ $y = [ 1, 2, 3 ] @ $z = [ a:"foo", b:10 ] $size($x) $size($y) $size($z) $size($undef) | 0 3 2 0 |
Funkcja $strlen zwraca d³ugo¶æ napisu.
$strlen() | |
---|---|
@ $x = 1 @ $y = "Foo Bar" $strlen($x) $strlen($y) $strlen($undef) | 0 7 0 |
$substr() | |
---|---|
$substr( "ABCDEFGHIJK", 2, 5 ) $substr( "ABCDEFGHIJK", 2 ) $substr( "ABCDEFGHIJK", 2, 50 ) | CDEFG CDEFGHIJK CDEFGHIJK |
$system() | |
---|---|
$system("ps") | PID TTY TIME CMD 348 pts/0 00:00:00 bash 713 pts/0 00:00:00 tg 714 pts/0 00:00:00 ps |
$tplfile(), $tplline() | |
---|---|
\#line $tplline() \"$tplfile()\" | #line 2 "sample.tg" |